#version 130

uniform vec3 EmitterPosition;
uniform vec3 EmitterDirection;
uniform float Time;
uniform float TimeStep;

in vec3 Position;
in vec3 Velocity;
in float Life;

out vec3 vPosition;
out vec3 vVelocity;
out float vLife;

const float TwoPi = 6.28318530718;
const float UINT_MAX = 4294967295.0;
const float InitialBand = 0.1;
const float SeedRadius = 0.3;
const float PlumeCeiling = 0.3;
const float VelocityStartingDeviation = 0.1;
const float VelocityYDeviation = 0.001;
const float VelocityXZDeviation = 0.001;

uint randhash(uint seed)
{
    uint i=(seed^12345391u)*2654435769u;
    i^=(i<<6u)^(i>>26u);
    i*=2654435769u;
    i+=(i<<5u)^(i>>12u);
    return i;
}

float randhashf(uint seed, float b)
{
    return float(b * randhash(seed)) / UINT_MAX;
}

void main()
{
	uint seed = uint( Time * 1000.0 ) + uint( gl_VertexID );

	if ( Life < -1.00f )
	{
		vPosition = vec3( 0.0f, 0.0f, 0.0f );

		float theta = randhashf( seed++, TwoPi );
		float r = randhashf( seed++, SeedRadius );
		float y = randhashf( seed++, InitialBand );

		vPosition = EmitterPosition;
		vPosition.x += r * cos( theta );
		vPosition.y += y;
		vPosition.z += r * sin( theta );

		vec3 startingVelocity = normalize( EmitterDirection );
		startingVelocity.x += randhashf( seed++, VelocityStartingDeviation );
		startingVelocity.y += randhashf( seed++, VelocityStartingDeviation );
		startingVelocity.z += randhashf( seed++, VelocityStartingDeviation );

		vVelocity = startingVelocity * 5;

		vLife = randhashf( seed++, 1.0f );
		vLife *= ( 1 - ( r / SeedRadius )*( r / SeedRadius ) );
	}
	else
	{
		vPosition = Position;

		// Fire
		if ( Life > 0.0f )
		{
			vVelocity = Velocity;
			vVelocity.x += 0.01 * randhashf( seed++, ( EmitterDirection.x - vVelocity.x ) );
			vVelocity.y += 0.01 * randhashf( seed++, ( EmitterDirection.y - vVelocity.y ) );
			vVelocity.z += 0.01 * randhashf( seed++, ( EmitterDirection.z - vVelocity.z ) );

			vVelocity.x *= 0.99f;
			vVelocity.y *= 1.005f;
			vVelocity.z *= 0.99f;

			float lifeRemoved = randhashf( seed++, 0.02 );
			vLife = Life - lifeRemoved;
		}
		else // Smoke
		{
			vVelocity = Velocity;

			if ( Position.y < PlumeCeiling + EmitterPosition.y )
			{
				vLife = -0.7f;
				float lifeRemoved = randhashf( seed++, 0.02 );
				vLife = Life - lifeRemoved;

				//vVelocity.y *= 1.005f;
			}
			else
			{
				vVelocity.x += randhashf( seed++, ( 1 ) ) - 0.5;
				vVelocity.z += randhashf( seed++, ( 1 ) ) - 0.5;
				//vVelocity.y += 0.5 * randhashf( seed++, ( 1 ) );


				//vVelocity.x *= 0.95f;
				//vVelocity.z *= 0.95f;
				//vVelocity.y *= 0.99f;

				float lifeRemoved = randhashf( seed++, 0.01 );
				vLife = Life - lifeRemoved;
			}
		}
	}

	//float rand = randhashf( seed++, 1.0f );
	//vec3 randDirection = vec3( rand, rand, rand );
	//randDirection = normalize( randDirection );
	//vPosition += 0.01 * EmitterDirection;

	vPosition += TimeStep * vVelocity;
}
